package com.ansion.basedb.storage;

import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;

import com.ansion.basedb.database.IDatabaseManager;
import com.ansion.basedb.database.TrackHelper;
import com.ansion.basedb.database.zoom.ThirdPartDataBase;
import com.ansion.basedb.storage.api.BaseKeyValueStorage;
import com.ansion.basedb.storage.api.EncSpStorage;
import com.ansion.basedb.storage.api.MMKVStorage;
import com.ansion.basedb.storage.api.SpStorage;
import com.ansion.basedb.storage.api.StorageMode;
import com.ansion.basedb.storage.secure.SpStorageImpl;
import com.ansion.constant.BConstant;
import com.ansion.log.VLog;
import com.ansion.string.StringUtils;
import com.ansion.utils.ContactUtil;
import com.ansion.utils.ResourceUtils;
import com.ansion.utils.SharedPref;

import java.util.List;


/***
 * @author john 2022/1/22
 * @desc 存储sdk
 * 备注：基于代码隔离的思想，SDK只暴露有限的接口和pojo。理论上需要再抽取一个storage_domain/storage_api
 */
public class StorageSdk {
//    private static DemoCacheDao demoCacheDao;
//    private static MPFileJournalCacheDao mpFileJournalCacheDao;
//    private static CheckInCacheDao checkInCacheDao;
//    private static TrackCacheDao trackCacheDao;
//
//    private static IdentityKeyDao identityKeyCacheDao;
//    private static E2EESessionDao e2EeE2EESessionDao;
//    private static PreKeyDao preKeyDao;
//    private static SignedPreKeyDao signedPreKeyDao;
//
//
//    private static DeviceKeyVersionCacheDao deviceKeyVersionCacheDao;
//    private static SessionKeyVersionCacheDao sessionKeyVersionCacheDao;
//
//    private static ResendMessageDao resendMessageDao;
//
//    private static DecryptFailMessageDao decryptFailMessageDao;
//    private static DeleteMessageCacheDao deleteMessageCacheDao;
    @Deprecated
    public static BaseKeyValueStorage getStorage() {
        return StorageManager.getStorage(BConstant.Storage.COMMON_TABLE_NAME);
    }

    @Deprecated
    public static BaseKeyValueStorage getTokenStorage() {
        return StorageManager.getStorage(BConstant.Storage.COMMON_TOKEN_TABLE_NAME);
    }

    /***
     * 一台设备一个本地配置文件，所有账号共用一个，退出登陆、删账号只清数据，不删该文件
     * @return
     */
    public static BaseKeyValueStorage getConfigStorage() {
        return StorageManager.getStorage(BConstant.Storage.CONFIG_TABLE_NAME);
    }

    /**
     * 这个存储退出登录就会清空。
     */
    public static BaseKeyValueStorage getCommonStorage() {
        String myUid = ContactUtil.getMyUid();
        if (StringUtils.isNonEmpty(myUid)) {
            myUid = "_" + myUid.hashCode();
        }
        return StorageManager.getStorage(BConstant.Storage.COMMON_TABLE_NAME + myUid);
    }

    /**
     * 这个存储退出登录不会清空，只有删除账号会清空。
     */
    public static BaseKeyValueStorage getUserConfigStorage() {
        return StorageManager.getStorage(BConstant.Storage.CONFIG_TABLE_NAME + ContactUtil.getMyUid());
    }

    public static void deleteUserConfigStorage(long uid) {
        removeStorage(BConstant.Storage.CONFIG_TABLE_NAME + uid, StorageMode.MODE_MMKV);
    }


    private static void deleteCommonStorage() {
        String myUid = ContactUtil.getMyUid();
        if (StringUtils.isNonEmpty(myUid)) {
            myUid = "_" + myUid.hashCode();
        }
        removeStorage(BConstant.Storage.COMMON_TABLE_NAME + myUid, StorageMode.MODE_MMKV);
    }

    public static BaseKeyValueStorage getStorage(@NonNull String name) {
        return StorageManager.getStorage(name);
    }

    /***
     * 获取指定类型的kvsStorage
     * @param mode 0为MMKV实现，1为SQLite实现，2为sp实现
     * @param name 配置文件名称
     * @return
     */
    public static BaseKeyValueStorage getStorage(@StorageMode int mode, @NonNull String name) {
        return StorageManager.getStorage(name, mode);
    }


    /**
     * 账户退出登陆逻辑，清除kvs内存；BaseDaoManager flushDao，clearMemoryCache
     */
    public static void appSignOut() {
        //deleteCommonStorage放在sdk的appSignOut中，不给外部调用
        deleteCommonStorage();
        StorageManager.clear();
        //需要注意的新加的dao在退出登录后一定要调用一下logout，避免查错数据
//        if (demoCacheDao != null) {//不为空说明使用过，需要调用onLogout
//            demoCacheDao.onLogout();
//        }
//
//        if (mpFileJournalCacheDao != null) {
//            mpFileJournalCacheDao.onLogout();
//        }
//
//
//        if (deviceKeyVersionCacheDao != null) {
//            deviceKeyVersionCacheDao.onLogout();
//        }
//        if (sessionKeyVersionCacheDao != null) {
//            sessionKeyVersionCacheDao.onLogout();
//        }
//
//        if (resendMessageDao != null)
//            resendMessageDao.onLogout();
//        if (decryptFailMessageDao != null)
//            decryptFailMessageDao.onLogout();
//        if (checkInCacheDao != null) {
//            checkInCacheDao.onLogout();
//        }

        //切记，这个ThirdPartDataBase.release一定要放在最后，避免flush数据的时候数据库已经关闭
        ThirdPartDataBase.release();
    }

    /**
     * 删账户的时候删数据库
     *
     * @param uid
     */
    public static void deleteAccount(long uid) {
        ThirdPartDataBase.deleteAccount(uid);
        deleteUserConfigStorage(uid);
    }


    public static void removeStorage(@NonNull String tableName, @StorageMode int mode) {
        VLog.i("TAG_STORAGE", "removeStorage %s,mode:%d", tableName, mode);
        //todo 实现删除功能
        try {
            int finalMode = StorageManager.getFinalMode(mode, StorageMode.MODE_SP);
            if (finalMode == StorageMode.MODE_MMKV) {
                BaseKeyValueStorage kvs = getStorage(mode, tableName);
                if (kvs instanceof MMKVStorage) {
                    ((MMKVStorage) kvs).clearAll();
                }
            } else if (finalMode == StorageMode.MODE_SP) {
                String spName = SpStorageImpl.getName(tableName);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    ResourceUtils.getContext().deleteSharedPreferences(spName);
                } else {
                    BaseKeyValueStorage kvs = getStorage(mode, tableName);
                    if (kvs instanceof SpStorage) {
                        ((SpStorage) kvs).clearAll();
                    }
                }
            } else if (finalMode == StorageMode.MODE_ESP) {
                String spName = SecureStorePreference.getName(tableName);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    ResourceUtils.getContext().deleteSharedPreferences(spName);
                } else {
                    BaseKeyValueStorage kvs = getStorage(mode, tableName);
                    if (kvs instanceof EncSpStorage) {
                        ((EncSpStorage) kvs).clearAll();
                    }
                }
            }
        } catch (Exception e) {
            VLog.e("TAG_STORAGE", "remove storage fail:" + e.getMessage());
        }


    }


    public static void initDataBase(IDatabaseManager databaseManager) {
        mainDB = databaseManager;
    }

    private static IDatabaseManager mainDB;

    public static IDatabaseManager getMainDB() {
        return mainDB;
    }


    public static SupportSQLiteDatabase getRoomDataBase(boolean readOnly) {
        SupportSQLiteOpenHelper openHelper = ThirdPartDataBase.getDataBaseInstance().getOpenHelper();
        if (readOnly)
            openHelper.getReadableDatabase();
        return openHelper.getWritableDatabase();
    }

    public static void clearDB() {
        mainDB = null;
    }
    public static MMKVStorage getMMKVStorage(@NonNull String name, boolean encrypt) {
        return LiteStorageManager.getInstance().getStorage(name, encrypt);
    }
//    public static DemoCacheDao getDemoCacheDao() {
//        if (demoCacheDao == null) {
//            synchronized (DemoCacheDao.class) {
//                if (demoCacheDao == null) {//使用size2测试
//                    demoCacheDao = new DemoCacheDao(20);
//                }
//            }
//        }
//        return demoCacheDao;
//    }

//    public static boolean syncSaveKeyBundle(@NonNull String loginUid, @NonNull SignedPreKeyEntity signedPreKey, @NonNull List<PreKeyEntity> preKeys) {
//        VLog.FileLog.i("TAG_E2E", "syncSaveKeyBundle start");
//        SupportSQLiteDatabase db = null;
//        boolean ret = false;
//        try {//keep this code, because the db instance may be changed
//            db = ThirdPartDataBase.getDataBaseInstance(loginUid).getOpenHelper().getWritableDatabase();
//            db.beginTransaction();
//            db.insert(SignedPreKeyEntity.TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, signedPreKey.toContentValues());
//            for (PreKeyEntity preKey : preKeys) {
//                db.insert(PreKeyEntity.TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, preKey.toContentValues());
//            }
//            db.setTransactionSuccessful();
//            ret = true;
//        } catch (Exception e) {
//            VLog.FileLog.e(e, "TAG_E2E", "syncSaveKeyBundle fail");
//            String message = String.format("KeyBundle saveToDb error,signedPreKeyId:%s", signedPreKey.getKeyId());
//            TrackHelper.trackDBSaveError(message, e, loginUid);
//        } finally {
//            if (db != null) {
//                db.endTransaction();
//            }
//        }
//        VLog.FileLog.i("TAG_E2E", "syncSaveKeyBundle end ret:%s", ret);
//        return ret;
//    }

}
